package com.example.ddz.framework.impl;

/**
 * Created by IntelliJ IDEA.
 * User: Marcel Melzig
 * Date: 26.07.11
 * Time: 19:39
 */

import java.util.ArrayList;
import java.util.List;

import android.view.View;
import android.view.View.OnKeyListener;

import com.example.ddz.framework.IInput.KeyEvent;
import com.example.ddz.framework.Pooling;
import com.example.ddz.framework.Pooling.PoolObjectFactory;

/**
 * This class handles the keyboard events.
 */
public class KeyboardHandler implements OnKeyListener
{
    private final boolean[] pressedKeys = new boolean[128];
    private final Pooling<KeyEvent> keyEventPool;
    private final List<KeyEvent> keyEventsBuffer = new ArrayList<KeyEvent>();
    private final List<KeyEvent> keyEvents = new ArrayList<KeyEvent>();

    /**
     * Creates an instance of this class and stores the fired key events in the pool.
     *
     * @param view The view which fires the key events.
     */
    public KeyboardHandler(View view)
    {
        PoolObjectFactory<KeyEvent> factory = new PoolObjectFactory<KeyEvent>()
        {
            @Override
            public KeyEvent createObject()
            {
                return new KeyEvent();
            }
        };
        keyEventPool = new Pooling<KeyEvent>(factory, 100);
        view.setOnKeyListener(this);
        view.setFocusableInTouchMode(true);
        view.requestFocus();
    }

    /**
     * Stores the fired key event in the pool.
     *
     * @param v       The view which fires the key event.
     * @param keyCode The keycode of the pressed key.
     * @param event   The event object.
     * @return A boolean which defines the state of the key.
     */
    @Override
    public boolean onKey(View v, int keyCode, android.view.KeyEvent event)
    {
        if (event.getAction() == android.view.KeyEvent.ACTION_MULTIPLE)
            return false;
        synchronized (this)
        {
            KeyEvent keyEvent = keyEventPool.NewObject();
            keyEvent.keyCode = keyCode;
            keyEvent.keyChar = (char) event.getUnicodeChar();
            if (event.getAction() == android.view.KeyEvent.ACTION_DOWN)
            {
                keyEvent.type = KeyEvent.KEY_DOWN;
                if (keyCode > 0 && keyCode < 127)
                    pressedKeys[keyCode] = true;
            }
            if (event.getAction() == android.view.KeyEvent.ACTION_UP)
            {
                keyEvent.type = KeyEvent.KEY_UP;
                if (keyCode > 0 && keyCode < 127)
                    pressedKeys[keyCode] = false;
            }
            keyEventsBuffer.add(keyEvent);
        }
        return false;
    }

    /**
     * Returns the pressed state of the pressed key.
     *
     * @param keyCode The keycode of the key.
     * @return The pressed state of the key.
     */
    public boolean IsKeyPressed(int keyCode)
    {
        return !(keyCode < 0 || keyCode > 127) && pressedKeys[keyCode];
    }

    /**
     * Recycles key events into from pool.
     *
     * @return A list of key events.
     */
    public List<KeyEvent> getKeyEvents()
    {
        synchronized (this)
        {
            for (KeyEvent keyEvent : keyEvents)
                keyEventPool.Free(keyEvent);

            keyEvents.clear();
            keyEvents.addAll(keyEventsBuffer);
            keyEventsBuffer.clear();
            return keyEvents;
        }
    }
}
